﻿#include "pch.h"
#include "SettingsPage.xaml.h"
#if __has_include("SettingsPage.g.cpp")
#include "SettingsPage.g.cpp"
#endif

#include <shobjidl_core.h>
#include "Utility.h"
#include <winrt/Windows.Storage.Pickers.h>
#include <winrt/Windows.Storage.h>
#include <Windows.h> // 包含 Windows API 函数
#pragma comment(lib, "User32.lib") // 链接 User32.lib 库
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
#include <memory>
#include <windows.h>
#include <iostream>
#include "../src/Logging.h"
#include <filesystem>
#include "../src/VersionControl.h"


using namespace winrt;
using namespace Microsoft::UI::Xaml;
//using namespace Windows::Foundation;
namespace wf = Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::ApplicationModel::DataTransfer;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.


// 函数：执行系统命令并获取输出
std::string execCommand(const char* cmd) 
{
    std::array<char, 128> buffer;
    std::string result;
    FILE* pipe = _popen(cmd, "rt");
    if (!pipe) {
        throw std::runtime_error("popen() failed!");
    }
    try {
        while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
            result += buffer.data();
        }
    }
    catch (...) {
        _pclose(pipe);
        throw;
    }
    _pclose(pipe);
    return result;
}

// 函数：判断路径是否为SVN仓库
bool isSvnRepository(const std::string& path) 
{
    // 检查路径下是否存在 .svn 文件夹
    std::string svnDirPath = path + "\\";
    svnDirPath += ".svn";
    DWORD attr = GetFileAttributesA(svnDirPath.c_str());
    return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY));
}

// 函数：获取SVN仓库的URL
std::string getSvnUrl(const std::string& path) 
{
    if (!isSvnRepository(path)) 
    {
        LOG_DEBUG("Not a SVN repository");
        return "";
    }

    // 构造 svn info 命令
    std::string command = "svn info \"" + path + "\" | findstr URL";
    std::string output = execCommand(command.c_str());

    // 提取 URL
    size_t startPos = output.find("URL: ");
    if (startPos != std::string::npos) 
    {
        startPos += 5; // 跳过 "URL: "
        size_t endPos = output.find("\n", startPos);
        if (endPos != std::string::npos) 
        {
            return output.substr(startPos, endPos - startPos);
        }
    }
    return "";
}

namespace winrt::GMTK::implementation
{
    int32_t SettingsPage::MyProperty()
    {
        throw hresult_not_implemented();
    }

    void SettingsPage::MyProperty(int32_t /* value */)
    {
        throw hresult_not_implemented();
    }

    // 提示弹窗
    void SettingsPage::ShowMessageDialog(const hstring& message)
	{
		winrt::Microsoft::UI::Xaml::Controls::ContentDialog dialog;
        dialog.XamlRoot(this->XamlRoot());
        dialog.Title(box_value(L"提示"));
		dialog.Content(box_value(message));
		dialog.CloseButtonText(L"确定");
		dialog.ShowAsync();

	}


    void SettingsPage::BtnAddProj_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
		const auto& projName = Text_ProjectName().Text();
		const auto& projPath = Text_ProjectPath().Text();
		const auto& projUrl = Text_SvnUrl().Text();

        if (projName.empty() || Utility::IsProjNameExist(to_string(projName)))
        {
			ShowMessageDialog(L"项目名为空或已存在");
            return;
        }

        if (projPath.empty() || projUrl.empty())
        {
			ShowMessageDialog(L"项目路径或SVN地址为空");
            return;
        }

		Utility::AddProj(to_string(projName), to_string(projPath), to_string(projUrl));
		ShowMessageDialog(L"添加成功");
    }


    void SettingsPage::BtnAddSuffix_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
		const auto& suffix = Text_SuffixName().Text();
		const auto& path = Text_SuffixPath().Text();

        if (suffix.empty() || Utility::IsSuffixExist(to_string(suffix)))
        {
			ShowMessageDialog(L"后缀名为空或已存在");
			return;
        }

        if (path.empty())
        {
            ShowMessageDialog(L"路径为空");
            return;
        }

		Utility::AddSuffix(to_string(suffix), to_string(path));
		ShowMessageDialog(L"添加成功");
    }

    void SettingsPage::BtnDelProj_Click(wf::IInspectable const& /*sender*/, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& /*e*/)
    {
        const auto& projName = Text_ProjectName().Text();
		if (projName.empty())
		{
			ShowMessageDialog(L"项目名为空");
			return;
		}

        if (!Utility::IsProjNameExist(to_string(projName)))
        {
            ShowMessageDialog(L"项目名不存在");
            return;
        }

		Utility::RemoveProj(to_string(projName));
		ShowMessageDialog(L"删除成功");
    }


    void SettingsPage::BtnDelSuffix_Click(wf::IInspectable const& /*sender*/, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& /*e*/)
    {
        const auto& suffix = Text_SuffixName().Text();
		if (suffix.empty())
		{
			ShowMessageDialog(L"后缀名为空");
			return;
		}

		if (!Utility::IsSuffixExist(to_string(suffix)))
		{
			ShowMessageDialog(L"后缀名不存在");
			return;
		}

		Utility::RemoveSuffix(to_string(suffix));
		ShowMessageDialog(L"删除成功");

    }

    // 已移除 TortoiseSVN 专用选择器（统一使用 BtnVcsClient_Click）


    wf::IAsyncAction SettingsPage::BtnBCompare_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
		using namespace Windows::Storage::Pickers;

		HWND hwnd = GetActiveWindow(); // 或者使用你自己的方法获取窗口句柄
		FileOpenPicker picker;
        {
            picker.as<IInitializeWithWindow>()->Initialize(hwnd);
        }
		picker.ViewMode(PickerViewMode::Thumbnail);
		picker.SuggestedStartLocation(PickerLocationId::Desktop);
		picker.FileTypeFilter().Append(L".exe");

        const auto& result = co_await picker.PickSingleFileAsync();
        if (result)
        {
            const auto& path = result.Path();
			Text_BCompare().Text(path);
        }
    }

    // 已移除 TortoiseSVN 专用保存（统一使用 BtnVcsClientSave_Click）


    void SettingsPage::BtnBCompareSave_Click(wf::IInspectable const& /* sender */, RoutedEventArgs const& /*e*/)
    {
        const auto& path = Text_BCompare().Text();
        if (path.empty())
        {
            ShowMessageDialog(L"路径为空");
            return;
        }
        const auto pathStr = to_string(path);
        if (!std::filesystem::exists(pathStr))
        {
            ShowMessageDialog(L"文件不存在，请检查路径");
            return;
        }
        Utility::SetComparePath(pathStr);
        ShowMessageDialog(L"保存成功");
    }

    wf::IAsyncAction SettingsPage::BtnVcsClient_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
        using namespace Windows::Storage::Pickers;

        HWND hwnd = GetActiveWindow();
        FileOpenPicker picker;
        {
            picker.as<IInitializeWithWindow>()->Initialize(hwnd);
        }
        picker.ViewMode(PickerViewMode::Thumbnail);
        picker.SuggestedStartLocation(PickerLocationId::Desktop);
        picker.FileTypeFilter().Append(L".exe");

        const auto& result = co_await picker.PickSingleFileAsync();
        if (result)
        {
            const auto& path = result.Path();
            Text_VcsClient().Text(path);
        }
    }

    void SettingsPage::BtnVcsClientSave_Click(wf::IInspectable const& /* sender */, RoutedEventArgs const& /*e*/)
    {
        const auto& path = Text_VcsClient().Text();
        const auto pathStr = to_string(path);
        // 允许空路径（走环境变量/默认 PATH），若非空则校验存在
        if (!pathStr.empty() && !std::filesystem::exists(pathStr))
        {
            ShowMessageDialog(L"文件不存在，请检查路径");
            return;
        }
        // 基于当前下拉选项决定：1) 保存当前版本控制类型 2) 保存对应客户端路径
        std::string sel;
        if (ComboBox_VcsType())
        {
            auto item = ComboBox_VcsType().SelectedItem().as<winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>();
            if (item) sel = to_string(unbox_value<hstring>(item.Content()));
        }
        if (sel == "TortoiseGIT")
        {
            Utility::SetVcsType(VcsType::TortoiseGIT);
            Utility::SetTortoiseGitPath(pathStr);
        }
        else if (sel == "TortoiseSVN")
        {
            Utility::SetVcsType(VcsType::TortoiseSVN);
            Utility::SetTortoiseSVNPath(pathStr);
        }
        else if (sel == "GIT")
        {
            Utility::SetVcsType(VcsType::GIT);
            Utility::SetGitCliPath(pathStr);
        }
        else /* SVN */
        {
            Utility::SetVcsType(VcsType::SVN);
            Utility::SetSvnCliPath(pathStr);
        }

        // 刷新一次 UI，更新标题与路径占位等
        RefreshVcsClientUi();
        ShowMessageDialog(L"版本控制类型与路径已保存");
    }

    void SettingsPage::ComboBox_VcsType_SelectionChanged(wf::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
    {
        RefreshVcsClientUi();
    }


    void SettingsPage::BtnSvnAuthorSave_Click(wf::IInspectable const& /* sender */, RoutedEventArgs const& /*e*/)
    {
        const auto& author = Text_SvnAuthor().Text();
		if (author.empty())
		{
			ShowMessageDialog(L"作者为空");
			return;
		}
		Utility::SetSvnAuthor(to_string(author));
        ShowMessageDialog(L"保存成功");
    }
    void SettingsPage::BtnLogLevelSave_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
        auto item = ComboBox_LogLevel().SelectedItem().as<winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>();
        if (!item)
        {
            ShowMessageDialog(L"请选择日志级别");
            return;
        }
        auto text = unbox_value<hstring>(item.Content());
        std::string s = to_string(text);
        Logging::Level lv = Logging::Level::Info;
        if (s == "Debug") lv = Logging::Level::Debug;
        else if (s == "Info") lv = Logging::Level::Info;
        else if (s == "Warn") lv = Logging::Level::Warn;
        else if (s == "Error") lv = Logging::Level::Error;
        Utility::SetLogMinLevel(lv);
        ShowMessageDialog(L"日志级别已保存");
    }

    void SettingsPage::BtnLogTogglesSave_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
        Utility::SetLogConsoleEnabled(Check_LogConsole().IsChecked().GetBoolean());
        Utility::SetLogFileEnabled(Check_LogFile().IsChecked().GetBoolean());
        ShowMessageDialog(L"日志输出开关已保存");
    }

    void SettingsPage::BtnLogFilePathSave_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
        auto path = Text_LogFilePath().Text();
        if (path.empty())
        {
            ShowMessageDialog(L"路径为空");
            return;
        }
        Utility::SetLogFilePath(to_string(path));
        ShowMessageDialog(L"日志文件路径已保存");
    }

    void SettingsPage::BtnOpenLogFolder_Click(wf::IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
    {
        std::string path = Logging::GetFilePath();
        if (path.empty())
        {
            path = Utility::GetWorkingDirectory() + "\\log.txt";
            Text_LogFilePath().Text(winrt::to_hstring(path));
        }
        // 打开目录
        try
        {
            std::filesystem::path p(path);
            auto dir = p.has_parent_path() ? p.parent_path().string() : p.string();
            Utility::OpenFolder(dir);
        }
        catch (...)
        {
            ShowMessageDialog(L"打开文件夹失败");
        }
    }

    void SettingsPage::OnNavigatedTo(winrt::Microsoft::UI::Xaml::Navigation::NavigationEventArgs const&)
    {
        auto minLv = Logging::GetMinLevel();
        int sel = 1; // 默认 Info
        switch (minLv)
        {
        case Logging::Level::Debug: sel = 0; break;
        case Logging::Level::Info:  sel = 1; break;
        case Logging::Level::Warn:  sel = 2; break;
        case Logging::Level::Error: sel = 3; break;
        default: break;
        }
        if (ComboBox_LogLevel())
        {
            ComboBox_LogLevel().SelectedIndex(sel);
        }
        if (Check_LogConsole()) Check_LogConsole().IsChecked(Logging::IsConsoleEnabled());
        if (Check_LogFile())    Check_LogFile().IsChecked(Logging::IsFileEnabled());
        if (Text_LogFilePath())
        {
            std::string setPath = Logging::GetFilePath();
            if (setPath.empty())
            {
                setPath = Utility::GetWorkingDirectory() + "\\log.txt";
            }
            Text_LogFilePath().Text(winrt::to_hstring(setPath));
        }

        // 初始化 VCS UI：动态填充四种类型
        if (ComboBox_VcsType())
        {
            ComboBox_VcsType().Items().Clear();

            auto makeItem = [](const wchar_t* text){
                winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem item; 
                item.Content(box_value(hstring(text))); 
                return item; };

            // 顺序：TortoiseSVN、TortoiseGIT、SVN、GIT
            ComboBox_VcsType().Items().Append(makeItem(L"TortoiseSVN"));
            ComboBox_VcsType().Items().Append(makeItem(L"TortoiseGIT"));
            ComboBox_VcsType().Items().Append(makeItem(L"SVN"));
            ComboBox_VcsType().Items().Append(makeItem(L"GIT"));

            int idx = 0;
            switch (Utility::GetVcsType())
            {
            case VcsType::TortoiseSVN: idx = 0; break;
            case VcsType::TortoiseGIT: idx = 1; break;
            case VcsType::SVN:         idx = 2; break;
            case VcsType::GIT:         idx = 3; break;
            default: break;
            }
            ComboBox_VcsType().SelectedIndex(idx);
        }
        RefreshVcsClientUi();
    }

    void SettingsPage::RefreshVcsClientUi()
    {
        bool useGit = (Utility::GetVcsType() == VcsType::GIT || Utility::GetVcsType() == VcsType::TortoiseGIT);
        bool useTortoise = (Utility::GetVcsType() == VcsType::TortoiseGIT || Utility::GetVcsType() == VcsType::TortoiseSVN);
        // 若下拉框已有选中项，则优先根据当前选择刷新（无需等待保存）
        if (ComboBox_VcsType())
        {
            auto selItem = ComboBox_VcsType().SelectedItem().as<winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>();
            if (selItem)
            {
                auto text = unbox_value<hstring>(selItem.Content());
                std::string s = to_string(text);
                if (s == "GIT") { useGit = true;  useTortoise = false; }
                else if (s == "SVN") { useGit = false; useTortoise = false; }
                else if (s == "TortoiseGIT") { useGit = true; useTortoise = true; }
                else /*TortoiseSVN*/ { useGit = false; useTortoise = true; }
            }
        }
        if (Text_VcsClient())
        {
            // Header 文案：svn/git 或 TortoiseSVN/TortoiseGit
            if (useTortoise)
            {
                Text_VcsClient().Header(box_value(useGit ? L"TortoiseGit" : L"TortoiseSVN"));
            }
            else
            {
                Text_VcsClient().Header(box_value(useGit ? L"git" : L"svn"));
            }
            // 路径：四种类型分别读取对应配置，CLI 允许为空，亦可通过此处设置显式路径
            std::string path = useTortoise
                ? (useGit ? Utility::tortoiseGitPath : Utility::tortoiseSVNPath)
                : (useGit ? Utility::gitCliPath      : Utility::svnCliPath);
            Text_VcsClient().Text(winrt::to_hstring(path));
            // 始终允许选择/保存，CLI 可用于覆盖 PATH
            if (BtnVcsClientSave()) BtnVcsClientSave().IsEnabled(true);
            if (BtnVcsClient())     BtnVcsClient().IsEnabled(true);
        }
    }


    void SettingsPage::Text_ProjectPath_DragOver(wf::IInspectable const& /*sender*/, DragEventArgs const& e)
    {
        if (e.DataView().Contains(StandardDataFormats::StorageItems()))
        {
            e.AcceptedOperation(DataPackageOperation::Copy);
        }
        else
        {
            e.AcceptedOperation(DataPackageOperation::None);
        }
    }


    wf::IAsyncAction SettingsPage::Text_ProjectPath_Drop(wf::IInspectable const& /*sender*/, DragEventArgs const& e)
    {
        auto dataPackageView = e.DataView();
        if (!dataPackageView.Contains(StandardDataFormats::StorageItems()))
        {
            co_return;
        }
        
        auto result = co_await dataPackageView.GetStorageItemsAsync();

        if (result.Size() > 0)
        {
            auto item = result.GetAt(0); // 获取第一个文件或文件夹
            auto path = item.Path();
            Text_ProjectPath().Text(path); // 显示路径
            
            auto strPath = winrt::to_string(path);
            if (isSvnRepository(strPath))
            {
                auto url = getSvnUrl(strPath);
                Text_SvnUrl().Text(winrt::to_hstring(url));
            }
        }
    }
}













